package com.authstr.auth.service.imip;

import cn.hutool.core.util.RandomUtil;
import com.authstr.auth.constant.CacheKey;
import com.authstr.auth.constant.CacheName;
import com.authstr.auth.mapper.inter.UserDao;
import com.authstr.auth.service.inter.RelationUserRoleService;
import com.authstr.auth.service.inter.UserService;
import com.authstr.auth.shiro.ShiroUtil;
import com.authstr.auth.utils.EhcacheUntil;
import com.authstr.auth.utils.MsgEnum;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.authstr.basic.exception.Assert;
import com.authstr.basic.exception.BaseExceptionEnum;
import com.authstr.basic.exception.ServiceException;
import com.authstr.basic.reqres.request.RequestPara;
import com.authstr.basic.reqres.utils.WebUtils;
import com.authstr.basic.util.Md5Salt;
import com.authstr.basic.web.service.BaseServiceImpl;
import com.authstr.model.base.BaseUser;
import com.authstr.model.base.relation.BaseRelationUserRole;
import com.authstr.model.base_enum.YesOrNotEnum;
import com.authstr.model.constant.AdminC;
import com.authstr.model.constant.BaseC;
import com.authstr.model.utils.ModelUtil;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl extends BaseServiceImpl<UserDao, BaseUser> implements UserService {
    @Autowired
    UserDao userDao;

    @Autowired
    RelationUserRoleService relationUserRoleService;

    @Autowired
    EhCacheCacheManager ehCacheCacheManager;

    @Override
    public Page query(@Param("page")Page page, String role_id, String gmt_create_start, String gmt_create_end, String account) {
        return userDao.query(page,role_id,gmt_create_start,gmt_create_end,account);
    }

    public static void main(String[] args) {

    }

    /**
     * 添加或编辑用户
     * 可选参数:
     *      role_ids  角色id数组
     * @param model
     */
    @Transactional(rollbackFor=Exception.class)
    @Override
    public Long addOrEdit(BaseUser model, RequestPara  para){
        BaseUser user_temp= getByAccount(model.getAccount());
        //如果user_temp不为空,但id一样,说明是进行不改名字的编辑,不视为用户名存在
        Assert.isTrue(user_temp==null||user_temp.getId().equals(model.getId()),"该账号已存在");
        Long id=null;
        if(ModelUtil.isNew(model)){
            if(!StringUtils.hasText(model.getName())){
                model.setName(model.getAccount());
            }
            //设置盐
            model.setSalt( RandomUtil.randomString(5));
            super.save(model);
        }
        id= model.getId();
        Assert.isTrue(id!=null,"添加用户失败");

        //修改密码
        String is_update_password=WebUtils.get("is_update_password");
        if(YesOrNotEnum.Y.getCodeTest().equals(is_update_password)){
            //密码md5加密后,用数据自身id作为盐,再次加密
            String md5Password= null;
            try {
                md5Password = Md5Salt.sec(String.valueOf(id),model.getPassword());
            } catch (Exception e) {
                throw new ServiceException(MsgEnum.ENCRYPT_ERROR);
            }
            model.setPassword(md5Password);
        }

        super.updateById(model);

        //删除shiro_cache内的 用户信息缓存
        EhcacheUntil.removeKeyCache(CacheName.SHIRO_CACHE, CacheKey.USER_AUTH_+model.getAccount());


        //设置用户的角色
        String[] role_ids=para.getArray("role_ids");

        if(role_ids!=null){
            Long[] role_ids_int= (Long[]) ConvertUtils.convert(role_ids, Long.class);
            saveRoleInfo(id,role_ids_int);
            //移除角色信息缓存
            EhcacheUntil.removeKeyCache(CacheName.SHIRO_CACHE,CacheKey.ROLES_BY_USERID_+id);
        }

        return model.getId();
    }

    @Transactional(rollbackFor=Exception.class)
    public void addUser(BaseUser model,Integer user_type,RequestPara  para){
        BaseUser user_temp= getByAccount(model.getAccount());
        Assert.isTrue(user_temp==null,MsgEnum.USER_EXIST);
        // 获取盐值和加密后的密码
        String salt = ShiroUtil.getRandomSalt(5);
        String password = ShiroUtil.md5(model.getPassword(), salt);

        if(!StringUtils.hasText(model.getName())){
            model.setName(model.getAccount());
        }

        //保存
        model.setSalt(salt);
        model.setPassword(password);
        model.setUser_type(user_type);
        model.setStatus(BaseC.COMMON_STATUS_NORMAL);
        super.save(model);

        //设置用户的角色
        String[] role_ids=para.getArray("role_ids");
        if(role_ids!=null){
            Long[] role_ids_int= (Long[]) ConvertUtils.convert(role_ids, Long.class);
            saveRoleInfo(model.getId(),role_ids_int);
        }
    }

    @Override
    public void register(BaseUser model,RequestPara  para){
        addUser(model,AdminC.USER_TYPE_COMMON,para);
    }


    /**
     * 为一个用户保存角色信息
     * @param userId
     * @param roleIds
     * @return
     */
    @Override
    @Transactional
    public Boolean saveRoleInfo(Long userId, Long[] roleIds){
        Assert.isTrue( userId!=null,"userId不能为空",true);
        Assert.isTrue( roleIds!=null,"roleIds不能为空",true);
            //删除当前用户的角色关联信息
        Map<String,Object> delete_where=new HashMap();
        delete_where.put("user_id",userId);
        relationUserRoleService.removeByMap(delete_where);

        //创建角色关联信息并保存
        List<BaseRelationUserRole> temp=new ArrayList();
        for(int i=0;i<roleIds.length;i++){
            BaseRelationUserRole relation=new BaseRelationUserRole();
            relation.setUser_id(userId);
            relation.setRole_id(roleIds[i]);
            temp.add(relation);
        }

        //删除shiro_cache内的 角色信息缓存
        EhcacheUntil.removeKeyCache(CacheName.SHIRO_CACHE,CacheKey.ROLES_BY_USERID_+userId);

        return relationUserRoleService.saveBatch(temp);
    }

    /**
     * 删除用户
     * @param ids
     */
    @Transactional(rollbackFor=Exception.class)
    @Override
    public void delete(Long[] ids){
        Assert.isTrue(ids!=null, BaseExceptionEnum.PARA_ERROR);
        for(int i=0;i<ids.length;i++){
            Long id=ids[i];
            Assert.isTrue( !id.equals(AdminC.ADMIN_USER_ID),"不能删除超级管理员!");
            Assert.isTrue(super.removeById(id),"第"+(i+1)+"条数据删除失败!");
        }
    }



    @Override
    public BaseUser getByAccount(String account){
        return userDao.getByAccount(account);
    }

}
